package com.yungu.swift.report.config;

import com.google.common.collect.Lists;
import com.yungu.swift.utils.DateUtils;
import com.yungu.swift.utils.JsonUtils;
import com.yungu.swift.utils.ReflectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;

import java.sql.Statement;
import java.util.*;

/**
 * @author : cuixiuyin
 * @date : 2019/12/31
 */
@Slf4j
@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})
public class ResultPlugin implements Interceptor {


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object results = invocation.proceed();
        if (results instanceof Collection && CollectionUtils.isNotEmpty((Collection) results)) {
            Collection collection = (Collection) results;
            // 结果集合
            List<Object> objects = Lists.newLinkedList();
            // 结果集按日期分组
            Map<String, Object> resultMap = toResultMap(collection);
            // 结果集按日期从小到大排序
            collection = sort(collection);
            Iterator it = collection.iterator();
            while (it.hasNext()) {
                Object result = it.next();
                if (result == null){
                    continue;
                }
                objects.add(result);
                Object recordDateObj = ReflectUtils.getFieldValue(result, "recordDate");
                if (recordDateObj == null) {
                    continue;
                }
                Date date = (Date) recordDateObj;
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                calendar.add(Calendar.DATE, 1);
                Date nextDate = calendar.getTime();
                String nextDateFormat = DateUtils.format(nextDate, "yyyy-MM-dd");
                // 如果列表中存在下一天记录，或者已经是最后一条，不构建虚拟记录
                Object o = resultMap.get(nextDateFormat);
                if (o != null || !it.hasNext()) {
                    continue;
                }
                Object newInstance = result.getClass().newInstance();
                ReflectUtils.setFieldValue(newInstance, "recordDate", nextDate);
                objects.add(newInstance);
            }
            return objects;
        }
        return results;
    }

    /**
     * 结果集排序
     *
     * @param collection
     * @return
     */
    private List<Object> sort(Collection collection) {
        Object[] objects = new Object[collection.size()];
        collection.toArray(objects);
        try {
            for (int i = 0; i < objects.length - 1; i++) {
                Object iObj = ReflectUtils.getFieldValue(objects[i], "recordDate");
                if (iObj == null) {
                    continue;
                }
                Date iDate = (Date) iObj;
                for (int j = i + 1; j < objects.length; j++) {
                    Object jObj = ReflectUtils.getFieldValue(objects[j], "recordDate");
                    if (jObj == null) {
                        continue;
                    }
                    Date jDate = (Date) jObj;
                    if (jDate.before(iDate)) {
                        Object temp = jObj;
                        objects[j] = objects[i];
                        objects[i] = temp;
                    }
                }
            }
        } catch (IllegalAccessException e) {
            log.error("ResultPlugin sort error.collection:{}", JsonUtils.toJSONString(collection), e);
        }
        List<Object> list = new LinkedList<>();
        for (Object object : objects) {
            list.add(object);
        }
        return list;
    }

    /**
     * 结果集按日期分组
     *
     * @param collection
     * @return
     */
    private Map<String, Object> toResultMap(Collection collection) {
        Map<String, Object> objectMap = new HashMap<>();
        for (Object result : collection) {
            if (result == null) continue;
            try {
                Object recordDate = ReflectUtils.getFieldValue(result, "recordDate");
                if (recordDate != null) {
                    objectMap.put(DateUtils.format((Date) recordDate, "yyyy-MM-dd"), result);
                }
            } catch (IllegalAccessException e) {
                log.error("ResultPlugin toResultMap error.collection:{}", JsonUtils.toJSONString(collection), e);
            }
        }
        return objectMap;
    }

    @Override
    public Object plugin(Object target) {
        // 读取 @Signature 中的配置，判断是否需要生成代理类
        if (target instanceof ResultSetHandler) {
            return Plugin.wrap(target, this);
        } else {
            return target;
        }
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
